#include "AsioIOServicePool.h"



AsioIOServicePool::AsioIOServicePool(std::size_t size) : m_ioServices(size), m_works(size), m_nextIOService(0)
{
    for (std::size_t i = 0; i < size; ++i) {
        m_works[i] = std::unique_ptr<Work>(new Work(m_ioServices[i]));
    }
    // 遍历多个ioservice，创建多个线程，每个线程内部启动ioservice
    for (std::size_t i = 0; i < m_ioServices.size(); ++i) {
        m_threads.emplace_back([this, i]() {
            m_ioServices[i].run();
        });
    }
}

AsioIOServicePool::~AsioIOServicePool()
{
    stop();
    std::cout << "AsioIOServicePool destruct" << std::endl;
}

// 使用 round-robin 的方式返回一个 io_service
boost::asio::io_context& AsioIOServicePool::getIOService()
{
    auto& service = m_ioServices[m_nextIOService++];
    if (m_nextIOService == m_ioServices.size()) {
        m_nextIOService = 0;
    }
    return service;
}

// 停止服务，回收资源，唤醒挂起的线程
void AsioIOServicePool::stop()
{
   // 因为仅仅执行work.reset并不能让iocontext从run的状态中退出
   // 当iocontext已经绑定了读或写的监听事件后，还需要手动stop该服务。
   // 回收iocontext
   for (auto& work : m_works) {
       // 把服务先停止
       work->get_io_context().stop();
       work.reset();
   }

   // 必须要等到所有线程安全退出之后，stop函数才能结束
   for (auto& t : m_threads) {
       t.join();
   }
}
